//
// Created by denglibin on 19-10-24.
//

/**
 *哲学家就餐问题
 * 5个线程代表5个哲学家
 * 5把锁代表5根筷子
 * 思路： 让哲学家拿到左边的额筷子，再尝试拿右边的筷子，右边的拿不到则释放左边的筷子。
 *  最后一个 反向（先拿右边的再尝试左边的） 防止震荡（所有哲学家都同时持有左边的筷子又同时去拿右边的筷子）
 *  思考其他方案？
 **/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
static pthread_mutex_t mutexs[5]  ={PTHREAD_MUTEX_INITIALIZER}; //5把锁

/**
 * 线程函数
 * @param arg
 * @return
 */
static void * t_fun(void * arg){
     int i = (int)arg;

         if (i < 4) {
             pthread_mutex_lock(mutexs + i); // 获取左边的筷子
             int ret = pthread_mutex_trylock(mutexs + i + 1);// 尝试获取右边的筷子
             if (ret == 0) { // 获取锁成功
                 printf("%d eating\n", i);
                 pthread_mutex_unlock(mutexs+i+1); // 释放锁
                 pthread_mutex_unlock(mutexs+i); // 释放锁
             } else { // 获取锁失败
                 // 释放已持有的锁（左边的筷子）
                 pthread_mutex_unlock(mutexs + i);
                 printf("%d thinking\n", i);
             }

         } else { // 最后一个哲学家
             pthread_mutex_lock(mutexs); //获取右边的筷子（就是第一个筷子）
             int ret = pthread_mutex_trylock(mutexs + i);// 尝试获取左边的筷子
             if (ret == 0) { // 获取锁成功
                 printf("%d eating\n", i);
                 pthread_mutex_unlock(mutexs+i);
                 pthread_mutex_unlock(mutexs);
             } else { // 获取锁失败
                 // 释放已持有的锁（左边的筷子）
                 pthread_mutex_unlock(mutexs + i);
                 printf("%d thinking\n", i);
             }

         }
}


 static int main_(){
    pthread_t ts[5]; // 5个线程
    for(int i = 0; i < 5; i++){
        pthread_create(ts + i, NULL, t_fun, (void *)i);
    }

    for(int i = 0; i < 5; i++){
        pthread_join(ts[i], NULL);
    }
    for(int i = 0; i < 5; i++){
        pthread_mutex_destroy(mutexs + i);
    }

    return 0;
}


